home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / Sample Code / Overview / ScreenFKey / ScreenFKEY.p < prev    next >
Encoding:
Text File  |  1994-11-18  |  9.2 KB  |  284 lines  |  [TEXT/MPS ]

  1. { pasmat -q -k -t 2 -: aFKEY6.p FKEY6.p -r -u }
  2.  
  3. {*#############################################################################################
  4. #                                                                   
  5. #    Apple Macintosh Developer Technical Support                        
  6. #                                                                   
  7. #    FKEY6 : Saves the contents of the main Macintosh screen to a PICT file.    
  8. #
  9. #    ScreenFKEY.p                                                           
  10. #                                                                   
  11. #    Copyright © 1989 Apple Computer, Inc.                            
  12. #    All rights reserved.                                            
  13. #                                                                    
  14. #    Versions:                                                            
  15. #            1.00                     10/89                            
  16. #                                                                   
  17. #    Components:                                                        
  18. #            ScreenFKEY.p            October 1, 1989                     
  19. #            ScreenFKEY.a              October 1, 1989                     
  20. #            ScreenFKEY.make          October 1, 1989                    
  21. #                                                                   
  22. #    ScreenFKEY is a basic example on how to spool a PICT file to disk by replacing the 
  23. #    bottleneck PutPICProc, it saves the contents of the screen to a file. The FKEY creates 
  24. #    ten files Screen 0 through Screen 9; it is necessary to erase or rename old files when 
  25. #    the limit is reached. 
  26. #    
  27. #    This FKEY works in any Macintosh computer and saves the screen regardless of the 
  28. #    setting of the screen; to use, it has to be added to the System file using ResEdit.
  29. #
  30. ############################################################################################*}
  31.  
  32.  
  33.  
  34. { The basic strategy is as follows:
  35.   1.- Make sure we can create the file.
  36.   2.- If Color QuickDraw is available then use a color port
  37.       else use a regular B/W port
  38.   3.- Replace the bottleneck procedure for our own putPict procedure
  39.   4.- Open a picture, 3 above guarantees that data will go to disk
  40.   5.- CopyBits the whole screen into itself causing the stuff to go
  41.       to the picture.
  42.   6.- Close the picture
  43.   7.- Finish the PICT file.
  44.   8.- Leave things (QDProcs, port) the way they were.       }
  45.  
  46. { Another point of interest is the technique used to provide pseudo
  47.   globals needed for the process to work by tagging the fields to the
  48.   end of the grafport record.           }
  49.  
  50. UNIT FKEY;
  51.  
  52. INTERFACE
  53.  
  54.     USES Types, Quickdraw, Events, Controls, Windows, TextEdit, Dialogs, Fonts,
  55.     Lists, Menus, Resources, Scrap, ToolUtils, 
  56.     OSUtils, Files, Devices, DeskBus, DiskInit, Disks, Errors, Memory, Retrace, SegLoad, Serial,
  57.     ShutDown, Slots, Sound, Start, Timer, Packages;
  58.  
  59. TYPE
  60.  
  61. { structure used to mantain some globals that can not be accessed
  62.   in the standard way when QD calls the bottleneck procedure   }
  63.  
  64.     GDataRec = RECORD
  65.         pHand: PicHandle; { picture being created }
  66.         gRef: INTEGER; { file reference number }
  67.         fileOK: BOOLEAN; { problems flag }
  68.     END;
  69.     
  70.     { now lets put together a port + our data structure      }
  71.     GportPlus = RECORD
  72.         TRUEPort: CGrafPort;
  73.         GDStuff: GDataRec;
  74.     END;
  75.     
  76.     GPPtr = ^GportPlus;
  77.  
  78. { main procedure for the FKEY }
  79. PROCEDURE PICTOut;
  80.  
  81. { PutPICTData replaces the standard bottleneck proc }
  82. PROCEDURE PutPICTData(dataPtr: Ptr;  byteCount: INTEGER);
  83.  
  84.  
  85.  
  86. IMPLEMENTATION
  87.  
  88. PROCEDURE PutPICTData{(dataPtr: Ptr; byteCount: INTEGER)};
  89.  
  90. VAR
  91.     longCount: LONGINT; { byte count }
  92.     myPortPlus: GPPtr; { global data pointer }
  93.  
  94. BEGIN
  95.  
  96.     GetPort(grafPtr(myPortPlus)); { to access the global data }
  97.     
  98.     longCount := byteCount;
  99.     
  100.     IF myPortPlus^.GDStuff.fileOK THEN BEGIN { do this only if file is still OK }
  101.         
  102.         IF FSWrite(myPortPlus^.GDStuff.gRef, longCount, dataPtr) <> noErr THEN
  103.             { something bad occurred, must delete file }
  104.             myPortPlus^.GDStuff.fileOK := FALSE;
  105.         
  106.         IF myPortPlus^.GDStuff.pHand <> NIL THEN { if the picture is already open }
  107.             { keep size up to date so QD }
  108.             { can adjust for oddness        }
  109.             myPortPlus^.GDStuff.pHand^^.picSize := myPortPlus^.GDStuff.pHand^^.picSize + longCount;
  110.     END
  111.  
  112. END;
  113.  
  114. { The main procedure of the FKEY.
  115.   This code installs the bottle neck procedure, opens the picture and does all
  116.   the house keeping.
  117. }
  118.  
  119. PROCEDURE PICTOut;
  120.  
  121. VAR
  122.     err: OSErr;
  123.     i: INTEGER;
  124.     longCount, longZero: LONGINT;
  125.     myProcs: CQDProcs;
  126.     myOldProcs: QDProcs;
  127.     
  128.     savePictSizeFrame: Picture;
  129.     
  130.     nameStr: Str255;
  131.     vrefnum: INTEGER;
  132.     bytesAvail: LONGINT;
  133.     
  134.     oldPort: grafPtr;
  135.     wPortPlus: GportPlus;
  136.     wPortPlusPtr: GPPtr;
  137.     myDev, aDev: GDHandle;
  138.     pictHand: PicHandle;
  139.     globalRef: INTEGER;
  140.     
  141.     theWorld: SysEnvRec;
  142.     
  143.     bitPtr: BitMapPtr;
  144.  
  145.     { We use this procedure to kill the file if something fails.
  146.     We don't want to leave files laying around, do we? }
  147.     PROCEDURE DeathKiss;
  148.     BEGIN
  149.         IF globalRef <> 0 THEN 
  150.             err := FSClose(globalRef);
  151.         
  152.         { close the file if it is open }
  153.         err := FSDelete(nameStr, vrefnum); { to make sure Delete works }
  154.         SysBeep(1); { Let the world know }
  155.         Exit(PICTOut); { and get out of here! }
  156.     END; {DeathKiss} 
  157.  
  158. BEGIN {PICTOut}
  159.  
  160.     err := SysEnvirons(1, theWorld); { Lets check if we have what we need }
  161.     
  162.     { initializing the pointer to port + global stuff}
  163.     wPortPlusPtr := @wPortPlus;
  164.     
  165.     { Init this variable to help exit procedure clean our stuff when we have to run away. }
  166.     globalRef := 0; { if not zero then a file is open }
  167.     
  168.     { first we see if it is possible to open file }
  169.     
  170.     IF GetVInfo(0, @nameStr, vrefnum, bytesAvail) <> noErr THEN
  171.         { get info on default volume }
  172.         DeathKiss; { error, get out of here! }
  173.  
  174.     { At this point we could check to see if there is room in the volume for the PICT file,
  175.     I chose not to because using a value for the maximun length could probably abort the
  176.     process when there is room for the actual length. I decided that it is better to fail
  177.     when trying to write than kill the saving without reason. }
  178.  
  179.     { We try to create a file 'Screen x' beginning with 0 up to 9, if ten
  180.     files exist we exit and abort the saving              }
  181.     nameStr := 'Screen 0'; { initial name }
  182.     REPEAT BEGIN
  183.         err := Create(nameStr, vrefnum, 'GAO.', 'PICT');
  184.         IF err <> noErr THEN BEGIN
  185.             IF err = dupFNErr THEN BEGIN { if file already there bump the name }
  186.                 nameStr[8] := Chr(Ord(nameStr[8]) + 1);
  187.                 IF nameStr[8] = ':' THEN { ten files should be enough }
  188.                     DeathKiss; { can't make more files, get out of here! }
  189.             END
  190.             ELSE
  191.                 DeathKiss; { error, get out of here! }
  192.         END
  193.     END UNTIL (err = noErr);
  194.     
  195.     IF FSOpen(nameStr, vrefnum, globalRef) <> 0 THEN { if error delete }
  196.         DeathKiss; { error, get out of here! }
  197.  
  198.     { file should be open at this point, so we try to write out the header for the pict file }
  199.     longZero := 0;
  200.     longCount := 4;
  201.     FOR i := 1 TO (532  DIV 4 ) DO BEGIN { init PICT header and then some }
  202.         err := FSWrite(globalRef, longCount, @longZero);
  203.         IF err <> noErr THEN
  204.         DeathKiss {error while file open, get out and kill file }
  205.     END;
  206.         
  207.     IF SetFPos(globalRef, fsFromStart, 522) <> noErr THEN
  208.         DeathKiss; {error while positioning file, exit }
  209.  
  210.     GetPort(oldPort); { save current port }
  211.     
  212.     { init global vars }
  213.     wPortPlus.GDStuff.gRef := globalRef; { for file accesses }
  214.     wPortPlus.GDStuff.pHand := NIL; { no picture when begining }
  215.     wPortPlus.GDStuff.fileOK := TRUE; { we hope }
  216.  
  217.     IF theWorld.hasColorQD THEN BEGIN
  218.         OpenCport(CGrafPtr(wPortPlusPtr)); { Lets get a color port }
  219.         SetStdCProcs(myProcs); { set its bottleneck procs }
  220.         grafPtr(wPortPlusPtr)^.grafProcs := @myProcs;
  221.         myProcs.putPicProc := @PutPICTData;
  222.         myDev := GetMainDevice; { to get to screen }
  223.         bitPtr := BitMapPtr(myDev^^.gdPMap^)
  224.     END ELSE BEGIN
  225.         Openport(grafPtr(wPortPlusPtr)); { Lets get an old style port }
  226.         SetStdProcs(myOldProcs); { set procs }
  227.         grafPtr(wPortPlusPtr)^.grafProcs := @myOldProcs;
  228.         myOldProcs.putPicProc := @PutPICTData;
  229.         bitPtr := BitMapPtr(@wPortPlusPtr^.TRUEPort.portPixMap)
  230.     END;
  231.  
  232.     ClipRect(bitPtr^.bounds); { Just in case, make sure clip region is OK. }
  233.     
  234.     pictHand := OpenPicture(bitPtr^.bounds);
  235.     
  236.     { On a Macintosh II + color port OpenPicture fails if the heap 
  237.     doesn't have at least 1000 bytes free, so we better check 
  238.     if we have a valid handle         }
  239.  
  240.     IF pictHand <> NIL THEN BEGIN
  241.         wPortPlus.GDStuff.pHand := pictHand; { now we have a handle }
  242.     
  243.         { CopyBits will call our procedure }
  244.         CopyBits(bitPtr^, bitPtr^, bitPtr^.bounds, bitPtr^.bounds, srcCopy, NIL);
  245.     
  246.         ClosePicture;
  247.     
  248.     { We need this later to complete file }
  249.         savePictSizeFrame := pictHand^^; 
  250.     
  251.         KillPicture(pictHand) { release all memory }
  252.         
  253.     END ELSE { no picture saved so we have to kill the file }
  254.         wPortPlus.GDStuff.fileOK := FALSE;
  255.  
  256.     { Now we proceed to clean up and to restore the port }
  257.     grafPtr(wPortPlusPtr)^.grafProcs := NIL;
  258.     SetPort(oldPort);
  259.     IF theWorld.hasColorQD THEN
  260.         { Lets get rid of the color port }
  261.         CloseCport(CGrafPtr(wPortPlusPtr))
  262.     ELSE
  263.         ClosePort(grafPtr(wPortPlusPtr)); {or get rid of the normal port}
  264.  
  265.     { after everything is back in good shape we can check if the copybits data
  266.     went to disk a O.K. and if there is a picture at all }
  267.     
  268.     IF NOT (wPortPlus.GDStuff.fileOK) THEN
  269.         DeathKiss; {error while saving file, exit }
  270.     
  271.     IF SetFPos(globalRef, fsFromStart, 512) <> noErr THEN
  272.         DeathKiss; {error while positioning file, exit }
  273.     
  274.     longCount := SizeOf(Picture);
  275.     IF FSWrite(globalRef, longCount, @savePictSizeFrame) <> noErr THEN
  276.         DeathKiss; {error while writing picture size and rect to file, exit }
  277.     
  278.     IF FSClose(globalRef) <> noErr THEN { now close the file }
  279.         DeathKiss; {error while closing file, exit }
  280.  
  281. END; {PICTOut}
  282.  
  283. END. { Unit FKEY }
  284.